"""
数据清洗提示词生成模块
此模块用于生成调用大模型API时的提示词，确保所有配置项都包含在提示词中
"""

import json
import logging
from typing import List, Dict, Any

# 设置日志
logger = logging.getLogger(__name__)

def generate_deepseek_prompt(products: List[Dict], config_manager) -> str:
    """
    为DeepSeek API生成优化的提示词，仅包含必要的配置，减小提示词大小
    
    Args:
        products: 商品数据列表
        config_manager: 配置管理器实例
        
    Returns:
        优化后的提示词字符串
    """
    # 获取所有配置项
    brands_list = config_manager.brands
    units_list = config_manager.units
    marketing_words = config_manager.marketing_words
    common_products = config_manager.common_products
    
    # 优化品牌列表 - 只发送当前批次中可能出现的品牌
    # 从当前产品名称中提取可能匹配的品牌，减少品牌列表大小
    possible_brands = set()
    all_product_text = " ".join([p.get('商品名称', '') for p in products])
    
    # 添加当前批次商品名称中可能包含的品牌
    for brand in brands_list:
        if brand in all_product_text:
            possible_brands.add(brand)
    
    # 如果匹配到的品牌太少，添加一些热门品牌作为样例
    if len(possible_brands) < 20 and len(brands_list) > 20:
        # 添加前20个品牌作为常见品牌样例
        possible_brands.update(brands_list[:20])
    
    # 确保至少有一些品牌样例
    filtered_brands = list(possible_brands)
    if len(filtered_brands) < 10 and len(brands_list) > 0:
        filtered_brands = brands_list[:min(50, len(brands_list))]
    
    # 构建单位转换信息 - 只包含最常用的转换规则
    conversion_rules = []
    common_units = set(units_list[:min(20, len(units_list))])
    for source_unit, target_unit in config_manager.standard_unit_map.items():
        if source_unit in config_manager.unit_conversion and source_unit in common_units:
            conversion_rules.append(f"{source_unit} → {target_unit}")
    
    # 记录配置项大小，用于调试
    logger.info(f"配置项统计: 全部品牌数量={len(brands_list)}, 筛选后品牌数量={len(filtered_brands)}, " 
                f"单位数量={len(units_list)}, 营销词数量={len(marketing_words)}")
                
    # 生成品牌样例，帮助模型理解品牌格式
    brand_examples = filtered_brands[:10] if len(filtered_brands) > 10 else filtered_brands
    brand_matches = []
    for brand in brand_examples:
        match_example = f"'{brand}' 识别为 '{brand}'"
        brand_matches.append(match_example)
    
    # 生成规格范围样例
    spec_range_examples = [
        "择优白玉黄瓜4.5-5斤（多仓就近发货） → spec_value=4.5, spec_unit=斤, specification='4.5-5斤'",
        "新鲜水果5~6公斤装 → spec_value=5, spec_unit=公斤, specification='5~6公斤'",
        "优选细盐400-500g → spec_value=400, spec_unit=g, specification='400-500g'"
    ]
    
    # 生成提示词
    prompt = f"""你是一位专业的商品数据清洗和标准化专家。请严格按照指示从商品名称中提取结构化信息。

配置信息:
1. 已知品牌列表：{', '.join(filtered_brands)}
2. 已知单位列表：{', '.join(units_list[:min(30, len(units_list))])}
3. 营销词列表（需要去除）：{', '.join(marketing_words[:min(30, len(marketing_words))])}
4. 单位转换规则：{', '.join(conversion_rules)}

数据说明：
- 输入数据包含两列：商品名称和商品价格
- 商品名称通常包含：品牌、品名、促销信息、规格信息、包装信息等
- 需要提取并标准化这些信息

提取要求（非常重要）：
1. 品牌识别规则：
   - 必须从商品名称中精确匹配已知品牌列表中的品牌
   - 只有100%精确匹配已知品牌列表中的品牌名称才能填写brand字段
   - 如果识别不到已知品牌，必须将brand字段留空
   - 不要猜测、推断或创建新品牌
   - 品牌匹配示例：
     {chr(10).join(f"     {i}" for i in brand_matches)}
   
2. 规格提取规则（对于范围值）：
   - 对于包含范围的规格（如"4.5-5斤"），提取完整文本作为规格
   - 数值使用范围的最小值（4.5）
   - 范围规格示例：
     {chr(10).join(f"     {i}" for i in spec_range_examples)}

输出JSON格式：
[
  {{
    "original_name": "原始商品名称",
    "original_price": 原始价格,
    "brand": "品牌(必须精确匹配已知品牌，否则留空)",
    "brand_in_database": true/false,
    "cleaned_name": "清洗后的品名",
    "spec_value": 规格数值,
    "spec_unit": "原始单位",
    "standard_unit": "标准单位",
    "standard_value": 转换后的标准数值,
    "standard_price": 标准单价
  }}
]

商品数据如下：
{json.dumps(products, ensure_ascii=False, indent=2)}
"""
    
    # 记录提示词大小
    logger.info(f"生成的提示词长度: {len(prompt)} 字符")
    
    return prompt

def prepare_product_data(df) -> List[Dict]:
    """
    从DataFrame准备商品数据，用于提交给大模型API
    
    Args:
        df: 包含商品数据的DataFrame
        
    Returns:
        商品数据列表
    """
    import pandas as pd
    
    # 检查可能的价格列名
    price_col = None
    possible_price_columns = ['商品价格', '价格', 'price', '单价']
    for col in possible_price_columns:
        if col in df.columns:
            price_col = col
            logger.info(f"找到价格列: {price_col}")
            break
    
    if price_col is None:
        logger.warning("未找到价格列，将使用0作为默认价格")
    
    product_data = []
    for idx, row in df.iterrows():
        # 获取商品名称，确保不为空
        name = str(row['商品名称']) if not pd.isna(row['商品名称']) else ""
        
        # 获取价格，处理可能的格式问题
        price = 0.0
        if price_col:
            try:
                price_value = row[price_col]
                if not pd.isna(price_value):
                    # 如果价格是字符串，尝试解析其中的数值
                    if isinstance(price_value, str):
                        # 去除货币符号和单位，只保留数字部分
                        import re
                        price_match = re.search(r'(\d+(?:\.\d+)?)', price_value)
                        if price_match:
                            price = float(price_match.group(1))
                    else:
                        price = float(price_value)
            except Exception as e:
                logger.warning(f"解析价格时出错: {e}, 行 {idx}, 价格值: {row.get(price_col)}")
        
        # 记录原始数据，便于调试
        if idx < 5 or idx % 100 == 0:  # 只记录前5行和每100行中的1行
            logger.info(f"准备数据 {idx}: 商品名称='{name}', 价格={price}")
        
        product_data.append({
            "商品名称": name,
            "商品价格": price
        })
    
    logger.info(f"共准备 {len(product_data)} 条数据用于DeepSeek处理")
    return product_data 